package io.gitee.zhangbinhub.admin.oauth.controller.api

import io.gitee.zhangbinhub.acp.boot.exceptions.WebException
import io.gitee.zhangbinhub.acp.boot.interfaces.LogAdapter
import io.gitee.zhangbinhub.acp.cloud.annotation.AcpCloudDuplicateSubmission
import io.gitee.zhangbinhub.acp.core.common.CommonTools
import io.gitee.zhangbinhub.admin.common.api.OauthApi
import io.gitee.zhangbinhub.admin.resource.server.base.BaseResourceServerController
import io.gitee.zhangbinhub.admin.common.vo.InfoVo
import io.gitee.zhangbinhub.admin.oauth.constant.OrgConfigExpression
import io.gitee.zhangbinhub.admin.oauth.domain.OrganizationDomain
import io.gitee.zhangbinhub.admin.oauth.entity.Organization
import io.gitee.zhangbinhub.admin.oauth.po.OrganizationPo
import io.gitee.zhangbinhub.admin.oauth.vo.OrganizationVo
import io.swagger.v3.oas.annotations.*
import io.swagger.v3.oas.annotations.responses.ApiResponse
import io.swagger.v3.oas.annotations.responses.ApiResponses
import io.swagger.v3.oas.annotations.tags.Tag
import jakarta.validation.Valid
import jakarta.validation.constraints.NotBlank
import jakarta.validation.constraints.NotEmpty
import jakarta.validation.constraints.NotNull
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.http.HttpStatus
import org.springframework.http.MediaType
import org.springframework.http.ResponseEntity
import org.springframework.security.access.prepost.PreAuthorize
import org.springframework.security.oauth2.server.resource.authentication.BearerTokenAuthentication
import org.springframework.validation.annotation.Validated
import org.springframework.web.bind.annotation.*

/**
 * @author zhang by 16/01/2019
 * @since JDK 11
 */
@Validated
@RestController
@RequestMapping(OauthApi.basePath)
@Tag(name = "机构信息")
class OrgController @Autowired
constructor(
    logAdapter: LogAdapter,
    private val organizationDomain: OrganizationDomain
) : BaseResourceServerController(logAdapter) {

    @Operation(summary = "获取机构列表", description = "查询所有机构列表")
    @GetMapping(value = [OauthApi.orgConfig], produces = [MediaType.APPLICATION_JSON_VALUE])
    fun orgList(): ResponseEntity<List<Organization>> = ResponseEntity.ok(organizationDomain.getOrgList())

    @Operation(summary = "获取可编辑的机构列表", description = "查询所有可编辑的机构列表")
    @GetMapping(value = [OauthApi.modifiableOrg], produces = [MediaType.APPLICATION_JSON_VALUE])
    @Throws(WebException::class)
    fun modOrgList(@Parameter(hidden = true) bearerTokenAuthentication: BearerTokenAuthentication): ResponseEntity<List<Organization>> =
        ResponseEntity.ok(organizationDomain.getModOrgList(bearerTokenAuthentication.name))

    @Operation(summary = "获取所属机构及其所有子机构列表（所属机构）")
    @GetMapping(value = [OauthApi.currAndAllChildrenOrg], produces = [MediaType.APPLICATION_JSON_VALUE])
    @Throws(WebException::class)
    fun currAndAllChildrenOrgList(@Parameter(hidden = true) bearerTokenAuthentication: BearerTokenAuthentication): ResponseEntity<List<Organization>> =
        ResponseEntity.ok(organizationDomain.getCurrAndAllChildrenForOrg(bearerTokenAuthentication.name))

    @Operation(summary = "获取所属机构及其所有子机构列表（管理机构）")
    @GetMapping(value = [OauthApi.currAndAllChildrenMngOrg], produces = [MediaType.APPLICATION_JSON_VALUE])
    @Throws(WebException::class)
    fun currAndAllChildrenForMngOrg(@Parameter(hidden = true) bearerTokenAuthentication: BearerTokenAuthentication): ResponseEntity<List<Organization>> =
        ResponseEntity.ok(organizationDomain.getCurrAndAllChildrenForMngOrg(bearerTokenAuthentication.name))

    @Operation(summary = "获取所属机构及其所有子机构列表（所有机构）")
    @GetMapping(value = [OauthApi.currAndAllChildrenAllOrg], produces = [MediaType.APPLICATION_JSON_VALUE])
    @Throws(WebException::class)
    fun currAndAllChildrenForAllOrg(@Parameter(hidden = true) bearerTokenAuthentication: BearerTokenAuthentication): ResponseEntity<List<Organization>> =
        ResponseEntity.ok(organizationDomain.getCurrAndAllChildrenForAllOrg(bearerTokenAuthentication.name))

    @Operation(summary = "新建机构信息", description = "名称、编码、上级ID、序号、关联用户")
    @ApiResponses(ApiResponse(responseCode = "201", description = "创建成功"))
    @PreAuthorize(OrgConfigExpression.orgAdd)
    @PutMapping(value = [OauthApi.orgConfig], produces = [MediaType.APPLICATION_JSON_VALUE])
    @AcpCloudDuplicateSubmission
    @Throws(WebException::class)
    fun add(
        @Parameter(hidden = true) bearerTokenAuthentication: BearerTokenAuthentication,
        @RequestBody @Valid organizationPo: OrganizationPo
    ): ResponseEntity<Organization> =
        organizationDomain.doCreate(bearerTokenAuthentication.name, organizationPo).let {
            ResponseEntity.status(HttpStatus.CREATED).body(it)
        }

    @Operation(summary = "删除指定的机构信息")
    @ApiResponses(ApiResponse(responseCode = "400", description = "参数校验不通过；没有权限做此操作；"))
    @PreAuthorize(OrgConfigExpression.orgDelete)
    @DeleteMapping(value = [OauthApi.orgConfig], produces = [MediaType.APPLICATION_JSON_VALUE])
    @Throws(WebException::class)
    fun delete(
        @Parameter(hidden = true) bearerTokenAuthentication: BearerTokenAuthentication,
        @Parameter(description = "id列表", required = true)
        @NotEmpty(message = "id不能为空")
        @NotNull(message = "id不能为空")
        @RequestBody
        idList: MutableList<String>
    ): ResponseEntity<InfoVo> =
        organizationDomain.doDelete(bearerTokenAuthentication.name, idList)
            .let { ResponseEntity.ok(InfoVo(message = "删除成功")) }

    @Operation(summary = "更新机构信息", description = "名称、编码、上级ID、序号、关联用户")
    @ApiResponses(
        ApiResponse(
            responseCode = "400",
            description = "参数校验不通过；没有权限做此操作；ID不能为空；找不到信息；"
        )
    )
    @PreAuthorize(OrgConfigExpression.orgUpdate)
    @PatchMapping(value = [OauthApi.orgConfig], produces = [MediaType.APPLICATION_JSON_VALUE])
    @AcpCloudDuplicateSubmission
    @Throws(WebException::class)
    fun update(
        @Parameter(hidden = true) bearerTokenAuthentication: BearerTokenAuthentication,
        @RequestBody @Valid organizationPo: OrganizationPo
    ): ResponseEntity<Organization> {
        if (CommonTools.isNullStr(organizationPo.id)) {
            throw WebException("ID不能为空")
        }
        return ResponseEntity.ok(organizationDomain.doUpdate(bearerTokenAuthentication.name, organizationPo))
    }

    @Operation(summary = "获取机构详细信息")
    @ApiResponses(ApiResponse(responseCode = "400", description = "参数校验不通过；ID不能为空；找不到信息；"))
    @PreAuthorize(OrgConfigExpression.orgQuery)
    @GetMapping(value = [OauthApi.orgConfig + "/{orgId}"], produces = [MediaType.APPLICATION_JSON_VALUE])
    @Throws(WebException::class)
    fun orgInfo(
        @Parameter(description = "机构id", required = true)
        @NotBlank(message = "机构id不能为空")
        @PathVariable
        orgId: String
    ): ResponseEntity<OrganizationVo> =
        ResponseEntity.ok(organizationDomain.getOrgInfo(orgId))

    @Operation(summary = "获取机构列表（编码或名称）")
    @ApiResponses(ApiResponse(responseCode = "400", description = "参数校验不通过；ID不能为空；找不到信息；"))
    @GetMapping(value = [OauthApi.orgConfig + "-by-code-or-name"], produces = [MediaType.APPLICATION_JSON_VALUE])
    @Throws(WebException::class)
    fun orgInfoByCodeOrName(
        @Parameter(description = "机构编码或名称", required = true)
        @NotBlank(message = "机构编码或名称不能为空")
        @RequestParam
        codeOrName: String
    ): ResponseEntity<MutableList<OrganizationVo>> =
        ResponseEntity.ok(organizationDomain.getOrgInfoByCodeOrName(codeOrName))
}